aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Images/thread.png
blob: aa5a461405c8143e49d0687fa5519962ee55c130 (plain)
ofshex dumpascii
0000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 40 00 00 00 40 08 06 00 00 00 aa 69 71 .PNG........IHDR...@...@......iq
0020 de 00 00 00 04 73 42 49 54 08 08 08 08 7c 08 64 88 00 00 00 09 70 48 59 73 00 00 01 bb 00 00 01 .....sBIT....|.d.....pHYs.......
0040 bb 01 3a ec e3 e2 00 00 00 19 74 45 58 74 53 6f 66 74 77 61 72 65 00 77 77 77 2e 69 6e 6b 73 63 ..:.......tEXtSoftware.www.inksc
0060 61 70 65 2e 6f 72 67 9b ee 3c 1a 00 00 09 69 49 44 41 54 78 da ed 5b 69 6c 54 55 14 c6 5d 63 e2 ape.org..<....iIDATx..[ilTU..]c.
0080 92 18 23 c6 1f 86 32 ad 65 69 81 52 68 29 dd a6 c5 25 fe 51 13 13 d7 c4 25 6a 8c 46 e3 1a 25 a8 ..#...2.ei.Rh)...%.Q....%j.F..%.
00a0 23 76 66 0a 2d 03 85 d2 d2 85 99 21 6a 42 fa 4b a3 10 e8 9b 96 c5 b6 b4 b5 40 f7 95 99 a1 68 db #vf.-......!jB.K.........@....h.
00c0 90 60 48 14 17 dc 9e f7 bb 9d d7 de 77 e7 dd f7 de 48 c9 bc 6a 49 6e 68 5f ef 7b 73 cf 77 cf f9 .`H.........w....H..jInh_.{s.w..
00e0 ce 77 ce 9d 37 4f 96 e5 79 33 31 26 26 26 bc e3 e3 e3 17 c9 90 75 46 fb d8 d8 58 d2 4c 7d e6 4c .w..7O..y31&&&.......uF...X.L}.L
0100 8c 19 79 08 31 2c c7 c0 70 76 54 fc e7 00 20 bb fa 58 0c 00 7c 31 07 c0 1c 00 73 00 cc 5e 00 0a ..y.1,..pvT......X..|1....s..^..
0120 bc a3 8b ec be f0 33 ec 70 37 9e d9 d8 3a 34 d6 c4 8f c6 9e ef 8e 15 ed ef 1d fa f8 eb 9e 61 65 ......3.p7...:4...............ae
0140 7c f0 55 5f 03 7f 7f a1 3f f8 e0 ac 00 e0 81 ed 23 d7 15 f8 43 3f 15 f8 42 b2 de b0 7b 83 72 fa |.U_....?.......#...C?..B...{.r.
0160 8e 13 72 a2 bb 51 5e e8 94 e8 48 22 3f a7 97 9f a4 7f e3 e7 e7 ef 3e 25 67 56 76 bf 6a 79 00 f2 ..r..Q^...H"?.........>%gVv.jy..
0180 77 87 52 8d 0c 5f 55 de 29 27 15 1f 9a 32 3c d1 dd 20 af dc 7e 9c fc ed 94 60 fe 49 0a 54 ca 96 w.R.._U.)'...2<.....~....`.I.T..
01a0 63 c7 2c 0f 40 81 37 f4 94 c8 f8 8c 9d 5d f2 3d c5 87 a7 0c b7 b9 1a e4 b4 b2 0e ba bb 5a f3 33 c.,.@.7......].=.............Z.3
01c0 2b 7b e4 7b 36 4d cf 5f 52 da 34 6e 79 00 0a 7d c1 e2 28 43 2a ba e5 e4 4d 47 18 c3 03 f2 f2 6d +{.{6M._R.4ny..}..(C*...MG.....m
01e0 ed 72 de ee 11 4d c3 d7 56 0d c8 8b 4b be 51 cd 4f db de 21 db 7d c1 d1 59 00 40 78 9f 62 c8 9a .r...M..V...K.Q.O..!.}..Y.@x.b..
0200 ca 5e 79 d1 e6 a3 53 86 2c 74 06 e4 65 5b db e4 dc da 61 4d c3 71 3d d5 73 8c 99 2f 91 f9 ad 72 .^y...S.,t..e[....aM.q=.s../...r
0220 1e 33 ff 81 cf 46 6e b2 76 08 f8 42 a3 59 55 7d aa 1d c4 80 61 b9 35 43 9a 86 23 04 56 94 7d 4b .3...Fn.v..B.YU}....a.5C..#.V.}K
0240 77 9a 71 77 39 bb 7a 30 7a fe 9e d3 99 96 05 20 6d 6b ff 7c 2c 9c 35 3c 65 4b 8b 9c a3 65 08 47 w.qw9.z0z.......mk.|,.5<eK...e.G
0260 70 ca 7c 84 ca 9a 5d bd 42 12 cd a9 1e 78 db b2 00 ac d8 d6 fe 02 bb 83 88 65 91 21 3c c1 21 05 p.|...].B....x...........e.!<.!.
0280 ae de d9 29 9c bf b6 aa 9f 7a d5 d2 d2 96 2e cb 02 b0 cc d3 fa 29 16 99 b5 ab cf d0 90 28 82 f3 ...).....z...........).......(..
02a0 6a 67 82 3c 8e 17 16 95 1c 3d 6f 59 00 f2 6a 86 6a 45 86 e7 d6 0e c9 29 06 04 c7 87 07 80 61 79 jg.<.....=oY..j.jE.....)......ay
02c0 01 c0 65 57 f7 5b 17 00 bb 2f 74 f8 92 08 8e d1 0b ac 50 82 76 40 2a 9d f2 0a 5f f8 0e 4b 02 40 ..eW.[.../t.......P.v@*..._..K.@
02e0 16 77 4e 25 75 29 c1 35 98 26 38 84 07 9b 36 13 89 50 82 5c d6 90 c6 eb 2c 07 c0 7d 9f 9e 9e cf .wN%u).5.&8...6..P.\....,..}....
0300 0a 9f 58 08 0e f9 3f 3a 3c da 84 42 29 bb b2 77 a3 e5 00 b0 fb 43 f7 c6 4a 70 b8 0e 29 6c 36 3c ..X...?:<..B)..w.....C..Jp..)l6<
0320 90 4e f1 fc 25 a5 cd c3 96 03 80 48 db bd 66 09 0e 63 35 e2 9c c9 ff f0 98 35 24 35 8a 80 02 8f .N..%......H..f..c5......5$5....
0340 40 49 d2 4c b0 f9 c8 05 cb 01 40 76 65 04 8b 5b 5a da ac 4b 70 48 91 aa 38 77 0b e3 7c 5a 2f 30 @I.L......@ve..[Z..KpH..8w..|Z/0
0360 84 88 7b d7 56 0f fc ea 70 c8 57 5a 0a 80 a5 9e 96 73 7a 04 07 19 0c 55 c8 d6 05 28 88 f2 05 71 ..{.V...p.WZ.....sz....U...(...q
0380 0e 5e 58 ca cc 07 21 42 35 4e 79 85 7f 24 c1 32 00 60 37 c8 a2 7e 36 ab f3 e1 25 39 35 83 ba 8d .^X...!B5Ny..$.2.`7..~6...%95...
03a0 12 76 3e 08 32 af 96 07 2a fc 90 65 00 c8 d9 15 b4 ad 24 8b 06 09 16 f8 a6 5d 99 36 3e 62 d0 f9 .v>.2...*..e......$......].6>b..
03c0 b8 9f 2d 9b 29 2f 08 e6 17 7a 43 1b 2c 03 00 21 b4 d7 d9 26 c7 92 92 26 95 e1 28 76 26 dd 37 28 ..-.)/...zC.,..!...&...&..(v&.7(
03e0 a8 06 47 28 69 46 67 8f a0 90 14 57 97 77 7e 63 19 00 32 2a ba 6a d4 75 bf a4 32 06 2e 0f 00 72 ..G(iFg....W.w~c..2*.j.u..2....r
0400 34 ca 61 e8 03 b6 1a 44 1a cc 11 94 cd 00 50 f1 2a a2 0e 2f 5a 06 80 42 5f a8 6e ba 71 d9 43 c9 4.a....D......P.*../Z..B_.n.q.C.
0420 8d 65 6e 76 40 e2 a6 7a 5a 65 84 0c 0b 1a 8c ca 60 e4 2e 3f 90 22 93 19 71 85 ec 91 59 d7 72 83 .env@..zZe......`..?."..q...Y.r.
0440 25 00 28 f0 86 fa 45 95 1c f1 0e ea de 22 40 14 6e 80 2e d0 52 7e d9 d5 03 34 a4 34 db 69 7b 42 %.(...E......"@.n...R~...4.4.i{B
0460 29 71 07 80 b6 c1 7d a1 3f 8d da e0 4a 2a 84 cb a3 bc 65 39 82 07 03 06 ae 22 f3 d4 69 73 b2 b9 )q....}.?...J*....e9....."..is..
0480 a2 ea 2a f9 83 4f c6 1d 80 ec ca a1 55 66 8c d7 94 b6 24 15 82 1b 90 ef d9 a2 49 2b 6c d2 cb a3 ..*..O......Uf....$.......I+l...
04a0 c5 92 dd 17 76 c7 1d 80 54 4f 5b 25 16 8f 5c 8d dd d5 93 bf 46 03 1d 24 70 03 88 90 d5 01 ac fb ....v...TO[%..\.....F..$p.......
04c0 23 1c 70 86 80 94 69 f7 86 f7 c5 1d 80 14 4f 4b ab 96 1b 43 fc 40 f6 8a 52 99 99 93 23 34 57 91 #.p...i.......OK...C.@..R...#4W.
04e0 0e 51 00 69 02 e2 6e f8 2b ee 00 10 85 56 0f f6 06 d1 25 15 37 c6 9c 06 cd 03 72 8a 8a 22 94 c9 .Q.i..n.+....V....%.7.....r.."..
0500 90 c5 ca f3 b3 76 9c b8 33 ae 00 90 c5 9d 51 b3 f6 20 95 b2 22 37 46 36 58 be ad 8d a6 cb 7c 41 .....v..3.....Q....."7F6X.....|A
0520 99 6c 5a 52 6f 69 26 5e d6 bf 2e 6e 00 14 56 05 6f 36 dc 35 45 17 30 39 3c 2a a6 77 1c a7 e9 4e .lZRoi&^...n..V.o6.5E.09<*.w...N
0540 5c 3a 73 92 7a f3 91 a9 c6 6b 5e cd d0 5b 71 03 60 9d ff 54 56 2c 6e 8c 14 a6 b0 be cd 15 cd fa \:s.z....k^..[q.`..TV,n.........
0560 30 12 22 09 21 85 3c 0f 0e 20 b5 3f 27 a9 d5 9d 25 12 16 27 63 35 68 61 51 fd a3 18 89 ee c0 82 0.".!.<....?'...%..'c5haQ.......
0580 4b 02 20 b7 66 f8 b5 7f 1f d3 41 ba 8b 70 6b d6 48 ed a1 94 ce d1 21 93 59 d1 fd 47 4a c9 c1 1b K...f.....A..pk.H.....!.Y..GJ...
05a0 cd 1a 9f e0 3c b8 84 7b fe b9 85 2e e9 65 f2 c7 2b 62 06 80 ec 64 37 95 b6 5b 5b a9 e2 8b 2e 59 ....<..{.....e..+b...d7..[[....Y
05c0 cd 0f dc 0b 57 67 ab 41 bd d2 19 05 14 04 d5 62 c8 69 97 d4 4d c2 e9 25 33 3b 9a 56 d5 71 0d 79 ....Wg.A.......b.i..M..%3;.V.q.y
05e0 6e 05 19 68 e0 fc 3d f5 59 ae 40 43 d2 a6 fa 3b 63 02 00 87 14 22 25 87 83 51 7b 0c 24 07 b7 67 n..h..=.Y.@C...;c...."%..Q{.$..g
0600 5b e1 f8 59 d4 22 c3 75 85 13 c0 23 9c aa fc 81 5c 7b 77 9e c3 61 d8 31 ba db 71 e8 16 9b 53 2a [..Y.".u...#....\{w..a.1..q...S*
0620 22 f7 fc 19 f1 b4 23 5a 9e 20 0e 81 da e1 f3 8a b4 4d 74 6b a7 40 e4 70 45 b8 68 95 c3 20 3f b6 ".....#Z.........Mtk.@.pE.h...?.
0640 91 aa d3 0a a7 21 90 ca 94 cd 4c 05 d9 49 fe 1f 65 af 25 b8 24 69 5e 5d dd 55 66 c2 22 d1 15 c8 .....!....L..I..e.%.$i^].Uf."...
0660 26 f7 fc 4e d7 ec ac 7f dd 14 00 6c 1b 9c 35 46 2f 05 c2 38 10 20 88 30 8b 00 b2 8c 33 86 36 52 &..N.......l..5F/..8...0....3.6R
0680 05 2d 32 68 80 24 ae a0 c2 81 09 78 a4 d0 1b 7c 83 1a e2 38 74 9b cd 25 6d 50 8c 21 a1 f1 9e 69 .-2h.$.....x...|...8t..%mP.!...i
06a0 62 74 4a 1f 45 9e 7b 21 cf 71 e8 6a 43 00 d0 06 37 4f 72 47 75 49 6e f2 c8 4b 3b 0d 42 2b 40 fc btJ.E.{!.q.jC...7OrGuIn..K;.B+@.
06c0 f0 f7 e0 b9 8a 97 14 fa c3 5e b5 31 81 f7 23 f3 7e 34 13 0a 91 70 b8 5e 01 2e b1 f8 40 aa 21 00 .........^.1..#.~4...p.^....@.!.
06e0 19 3b bb 4a b1 08 bd 0e 30 4f 5a 98 cf 16 3d d8 51 bd 1e 00 00 e4 cb 68 64 0c 0d b0 da 55 00 38 .;.J....0OZ...=.Q......hd....U.8
0700 f6 df a4 10 9c ed 13 29 d9 7c 7a 94 4e 44 3e e7 39 43 00 52 b6 34 0f b0 ad 6a b8 b5 a8 c3 0b 16 .......).|z.ND>.9C.R.4...j......
0720 67 bf 37 80 f0 58 51 d6 ae d3 f2 0a 52 22 e5 f9 04 85 92 a0 ad f6 33 df 26 8f b0 3c 09 83 fa a7 g.7..XQ.....R"........3.&..<....
pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media.TextFormatting;
using Tango.Scripting.Editors.Document;
using Tango.Scripting.Editors.Rendering;
using Tango.Scripting.Editors.Utils;

namespace Tango.Scripting.Editors.Editing
{
	static class CaretNavigationCommandHandler
	{
		/// <summary>
		/// Creates a new <see cref="TextAreaInputHandler"/> for the text area.
		/// </summary>
		public static TextAreaInputHandler Create(TextArea textArea)
		{
			TextAreaInputHandler handler = new TextAreaInputHandler(textArea);
			handler.CommandBindings.AddRange(CommandBindings);
			handler.InputBindings.AddRange(InputBindings);
			return handler;
		}
		
		static readonly List<CommandBinding> CommandBindings = new List<CommandBinding>();
		static readonly List<InputBinding> InputBindings = new List<InputBinding>();
		
		static void AddBinding(ICommand command, ModifierKeys modifiers, Key key, ExecutedRoutedEventHandler handler)
		{
			CommandBindings.Add(new CommandBinding(command, handler));
			InputBindings.Add(TextAreaDefaultInputHandler.CreateFrozenKeyBinding(command, modifiers, key));
		}
		
		static CaretNavigationCommandHandler()
		{
			const ModifierKeys None = ModifierKeys.None;
			const ModifierKeys Ctrl = ModifierKeys.Control;
			const ModifierKeys Shift = ModifierKeys.Shift;
			const ModifierKeys Alt = ModifierKeys.Alt;
			
			AddBinding(EditingCommands.MoveLeftByCharacter, None, Key.Left, OnMoveCaret(CaretMovementType.CharLeft));
			AddBinding(EditingCommands.SelectLeftByCharacter, Shift, Key.Left, OnMoveCaretExtendSelection(CaretMovementType.CharLeft));
			AddBinding(RectangleSelection.BoxSelectLeftByCharacter, Alt | Shift, Key.Left, OnMoveCaretBoxSelection(CaretMovementType.CharLeft));
			AddBinding(EditingCommands.MoveRightByCharacter, None, Key.Right, OnMoveCaret(CaretMovementType.CharRight));
			AddBinding(EditingCommands.SelectRightByCharacter, Shift, Key.Right, OnMoveCaretExtendSelection(CaretMovementType.CharRight));
			AddBinding(RectangleSelection.BoxSelectRightByCharacter, Alt | Shift, Key.Right, OnMoveCaretBoxSelection(CaretMovementType.CharRight));
			
			AddBinding(EditingCommands.MoveLeftByWord, Ctrl, Key.Left, OnMoveCaret(CaretMovementType.WordLeft));
			AddBinding(EditingCommands.SelectLeftByWord, Ctrl | Shift, Key.Left, OnMoveCaretExtendSelection(CaretMovementType.WordLeft));
			AddBinding(RectangleSelection.BoxSelectLeftByWord, Ctrl | Alt | Shift, Key.Left, OnMoveCaretBoxSelection(CaretMovementType.WordLeft));
			AddBinding(EditingCommands.MoveRightByWord, Ctrl, Key.Right, OnMoveCaret(CaretMovementType.WordRight));
			AddBinding(EditingCommands.SelectRightByWord, Ctrl | Shift, Key.Right, OnMoveCaretExtendSelection(CaretMovementType.WordRight));
			AddBinding(RectangleSelection.BoxSelectRightByWord, Ctrl | Alt | Shift, Key.Right, OnMoveCaretBoxSelection(CaretMovementType.WordRight));
			
			AddBinding(EditingCommands.MoveUpByLine, None, Key.Up, OnMoveCaret(CaretMovementType.LineUp));
			AddBinding(EditingCommands.SelectUpByLine, Shift, Key.Up, OnMoveCaretExtendSelection(CaretMovementType.LineUp));
			AddBinding(RectangleSelection.BoxSelectUpByLine, Alt | Shift, Key.Up, OnMoveCaretBoxSelection(CaretMovementType.LineUp));
			AddBinding(EditingCommands.MoveDownByLine, None, Key.Down, OnMoveCaret(CaretMovementType.LineDown));
			AddBinding(EditingCommands.SelectDownByLine, Shift, Key.Down, OnMoveCaretExtendSelection(CaretMovementType.LineDown));
			AddBinding(RectangleSelection.BoxSelectDownByLine, Alt | Shift, Key.Down, OnMoveCaretBoxSelection(CaretMovementType.LineDown));
			
			AddBinding(EditingCommands.MoveDownByPage, None, Key.PageDown, OnMoveCaret(CaretMovementType.PageDown));
			AddBinding(EditingCommands.SelectDownByPage, Shift, Key.PageDown, OnMoveCaretExtendSelection(CaretMovementType.PageDown));
			AddBinding(EditingCommands.MoveUpByPage, None, Key.PageUp, OnMoveCaret(CaretMovementType.PageUp));
			AddBinding(EditingCommands.SelectUpByPage, Shift, Key.PageUp, OnMoveCaretExtendSelection(CaretMovementType.PageUp));
			
			AddBinding(EditingCommands.MoveToLineStart, None, Key.Home, OnMoveCaret(CaretMovementType.LineStart));
			AddBinding(EditingCommands.SelectToLineStart, Shift, Key.Home, OnMoveCaretExtendSelection(CaretMovementType.LineStart));
			AddBinding(RectangleSelection.BoxSelectToLineStart, Alt | Shift, Key.Home, OnMoveCaretBoxSelection(CaretMovementType.LineStart));
			AddBinding(EditingCommands.MoveToLineEnd, None, Key.End, OnMoveCaret(CaretMovementType.LineEnd));
			AddBinding(EditingCommands.SelectToLineEnd, Shift, Key.End, OnMoveCaretExtendSelection(CaretMovementType.LineEnd));
			AddBinding(RectangleSelection.BoxSelectToLineEnd, Alt | Shift, Key.End, OnMoveCaretBoxSelection(CaretMovementType.LineEnd));
			
			AddBinding(EditingCommands.MoveToDocumentStart, Ctrl, Key.Home, OnMoveCaret(CaretMovementType.DocumentStart));
			AddBinding(EditingCommands.SelectToDocumentStart, Ctrl | Shift, Key.Home, OnMoveCaretExtendSelection(CaretMovementType.DocumentStart));
			AddBinding(EditingCommands.MoveToDocumentEnd, Ctrl, Key.End, OnMoveCaret(CaretMovementType.DocumentEnd));
			AddBinding(EditingCommands.SelectToDocumentEnd, Ctrl | Shift, Key.End, OnMoveCaretExtendSelection(CaretMovementType.DocumentEnd));
			
			CommandBindings.Add(new CommandBinding(ApplicationCommands.SelectAll, OnSelectAll));
			
			TextAreaDefaultInputHandler.WorkaroundWPFMemoryLeak(InputBindings);
		}
		
		static void OnSelectAll(object target, ExecutedRoutedEventArgs args)
		{
			TextArea textArea = GetTextArea(target);
			if (textArea != null && textArea.Document != null) {
				args.Handled = true;
				textArea.Caret.Offset = textArea.Document.TextLength;
				textArea.Selection = SimpleSelection.Create(textArea, 0, textArea.Document.TextLength);
			}
		}
		
		static TextArea GetTextArea(object target)
		{
			return target as TextArea;
		}
		
		enum CaretMovementType
		{
			CharLeft,
			CharRight,
			WordLeft,
			WordRight,
			LineUp,
			LineDown,
			PageUp,
			PageDown,
			LineStart,
			LineEnd,
			DocumentStart,
			DocumentEnd
		}
		
		static ExecutedRoutedEventHandler OnMoveCaret(CaretMovementType direction)
		{
			return (target, args) => {
				TextArea textArea = GetTextArea(target);
				if (textArea != null && textArea.Document != null) {
					args.Handled = true;
					textArea.ClearSelection();
					MoveCaret(textArea, direction);
					textArea.Caret.BringCaretToView();
				}
			};
		}
		
		static ExecutedRoutedEventHandler OnMoveCaretExtendSelection(CaretMovementType direction)
		{
			return (target, args) => {
				TextArea textArea = GetTextArea(target);
				if (textArea != null && textArea.Document != null) {
					args.Handled = true;
					TextViewPosition oldPosition = textArea.Caret.Position;
					MoveCaret(textArea, direction);
					textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position);
					if (!textArea.Document.IsInUpdate) // if we're inside a larger update (e.g. called by EditingCommandHandler.OnDelete()), avoid calculating the caret rectangle now
						textArea.Caret.BringCaretToView();
				}
			};
		}
		
		static ExecutedRoutedEventHandler OnMoveCaretBoxSelection(CaretMovementType direction)
		{
			return (target, args) => {
				TextArea textArea = GetTextArea(target);
				if (textArea != null && textArea.Document != null) {
					args.Handled = true;
					// First, convert the selection into a rectangle selection
					// (this is required so that virtual space gets enabled for the caret movement)
					if (textArea.Options.EnableRectangularSelection && !(textArea.Selection is RectangleSelection)) {
						if (textArea.Selection.IsEmpty) {
							textArea.Selection = new RectangleSelection(textArea, textArea.Caret.Position, textArea.Caret.Position);
						} else {
							// Convert normal selection to rectangle selection
							textArea.Selection = new RectangleSelection(textArea, textArea.Selection.StartPosition, textArea.Caret.Position);
						}
					}
					// Now move the caret and extend the selection
					TextViewPosition oldPosition = textArea.Caret.Position;
					MoveCaret(textArea, direction);
					textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position);
					textArea.Caret.BringCaretToView();
				}
			};
		}
		
		#region Caret movement
		static void MoveCaret(TextArea textArea, CaretMovementType direction)
		{
			DocumentLine caretLine = textArea.Document.GetLineByNumber(textArea.Caret.Line);
			VisualLine visualLine = textArea.TextView.GetOrConstructVisualLine(caretLine);
			TextViewPosition caretPosition = textArea.Caret.Position;
			TextLine textLine = visualLine.GetTextLine(caretPosition.VisualColumn);
			switch (direction) {
				case CaretMovementType.CharLeft:
					MoveCaretLeft(textArea, caretPosition, visualLine, CaretPositioningMode.Normal);
					break;
				case CaretMovementType.CharRight:
					MoveCaretRight(textArea, caretPosition, visualLine, CaretPositioningMode.Normal);
					break;
				case CaretMovementType.WordLeft:
					MoveCaretLeft(textArea, caretPosition, visualLine, CaretPositioningMode.WordStart);
					break;
				case CaretMovementType.WordRight:
					MoveCaretRight(textArea, caretPosition, visualLine, CaretPositioningMode.WordStart);
					break;
				case CaretMovementType.LineUp:
				case CaretMovementType.LineDown:
				case CaretMovementType.PageUp:
				case CaretMovementType.PageDown:
					MoveCaretUpDown(textArea, direction, visualLine, textLine, caretPosition.VisualColumn);
					break;
				case CaretMovementType.DocumentStart:
					SetCaretPosition(textArea, 0, 0);
					break;
				case CaretMovementType.DocumentEnd:
					SetCaretPosition(textArea, -1, textArea.Document.TextLength);
					break;
				case CaretMovementType.LineStart:
					MoveCaretToStartOfLine(textArea, visualLine);
					break;
				case CaretMovementType.LineEnd:
					MoveCaretToEndOfLine(textArea, visualLine);
					break;
				default:
					throw new NotSupportedException(direction.ToString());
			}
		}
		#endregion
		
		#region Home/End
		static void MoveCaretToStartOfLine(TextArea textArea, VisualLine visualLine)
		{
			int newVC = visualLine.GetNextCaretPosition(-1, LogicalDirection.Forward, CaretPositioningMode.WordStart, textArea.Selection.EnableVirtualSpace);
			if (newVC < 0)
				throw ThrowUtil.NoValidCaretPosition();
			// when the caret is already at the start of the text, jump to start before whitespace
			if (newVC == textArea.Caret.VisualColumn)
				newVC = 0;
			int offset = visualLine.FirstDocumentLine.Offset + visualLine.GetRelativeOffset(newVC);
			SetCaretPosition(textArea, newVC, offset);
		}
		
		static void MoveCaretToEndOfLine(TextArea textArea, VisualLine visualLine)
		{
			int newVC = visualLine.VisualLength;
			int offset = visualLine.FirstDocumentLine.Offset + visualLine.GetRelativeOffset(newVC);
			SetCaretPosition(textArea, newVC, offset);
		}
		#endregion
		
		#region By-character / By-word movement
		static void MoveCaretRight(TextArea textArea, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode)
		{
			int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Forward, mode, textArea.Selection.EnableVirtualSpace);
			if (pos >= 0) {
				SetCaretPosition(textArea, pos, visualLine.GetRelativeOffset(pos) + visualLine.FirstDocumentLine.Offset);
			} else {
				// move to start of next line
				DocumentLine nextDocumentLine = visualLine.LastDocumentLine.NextLine;
				if (nextDocumentLine != null) {
					VisualLine nextLine = textArea.TextView.GetOrConstructVisualLine(nextDocumentLine);
					pos = nextLine.GetNextCaretPosition(-1, LogicalDirection.Forward, mode, textArea.Selection.EnableVirtualSpace);
					if (pos < 0)
						throw ThrowUtil.NoValidCaretPosition();
					SetCaretPosition(textArea, pos, nextLine.GetRelativeOffset(pos) + nextLine.FirstDocumentLine.Offset);
				} else {
					// at end of document
					Debug.Assert(visualLine.LastDocumentLine.Offset + visualLine.LastDocumentLine.TotalLength == textArea.Document.TextLength);
					SetCaretPosition(textArea, -1, textArea.Document.TextLength);
				}
			}
		}
		
		static void MoveCaretLeft(TextArea textArea, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode)
		{
			int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Backward, mode, textArea.Selection.EnableVirtualSpace);
			if (pos >= 0) {
				SetCaretPosition(textArea, pos, visualLine.GetRelativeOffset(pos) + visualLine.FirstDocumentLine.Offset);
			} else {
				// move to end of previous line
				DocumentLine previousDocumentLine = visualLine.FirstDocumentLine.PreviousLine;
				if (previousDocumentLine != null) {
					VisualLine previousLine = textArea.TextView.GetOrConstructVisualLine(previousDocumentLine);
					pos = previousLine.GetNextCaretPosition(previousLine.VisualLength + 1, LogicalDirection.Backward, mode, textArea.Selection.EnableVirtualSpace);
					if (pos < 0)
						throw ThrowUtil.NoValidCaretPosition();
					SetCaretPosition(textArea, pos, previousLine.GetRelativeOffset(pos) + previousLine.FirstDocumentLine.Offset);
				} else {
					// at start of document
					Debug.Assert(visualLine.FirstDocumentLine.Offset == 0);
					SetCaretPosition(textArea, 0, 0);
				}
			}
		}
		#endregion

		#region Line+Page up/down
		static void MoveCaretUpDown(TextArea textArea, CaretMovementType direction, VisualLine visualLine, TextLine textLine, int caretVisualColumn)
		{
			// moving up/down happens using the desired visual X position
			double xPos = textArea.Caret.DesiredXPos;
			if (double.IsNaN(xPos))
				xPos = visualLine.GetTextLineVisualXPosition(textLine, caretVisualColumn);
			// now find the TextLine+VisualLine where the caret will end up in
			VisualLine targetVisualLine = visualLine;
			TextLine targetLine;
			int textLineIndex = visualLine.TextLines.IndexOf(textLine);
			switch (direction) {
				case CaretMovementType.LineUp:
					{
						// Move up: move to the previous TextLine in the same visual line
						// or move to the last TextLine of the previous visual line
						int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1;
						if (textLineIndex > 0) {
							targetLine = visualLine.TextLines[textLineIndex - 1];
						} else if (prevLineNumber >= 1) {
							DocumentLine prevLine = textArea.Document.GetLineByNumber(prevLineNumber);
							targetVisualLine = textArea.TextView.GetOrConstructVisualLine(prevLine);
							targetLine = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1];
						} else {
							targetLine = null;
						}
						break;
					}
				case CaretMovementType.LineDown:
					{
						// Move down: move to the next TextLine in the same visual line
						// or move to the first TextLine of the next visual line
						int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1;
						if (textLineIndex < visualLine.TextLines.Count - 1) {
							targetLine = visualLine.TextLines[textLineIndex + 1];
						} else if (nextLineNumber <= textArea.Document.LineCount) {
							DocumentLine nextLine = textArea.Document.GetLineByNumber(nextLineNumber);
							targetVisualLine = textArea.TextView.GetOrConstructVisualLine(nextLine);
							targetLine = targetVisualLine.TextLines[0];
						} else {
							targetLine = null;
						}
						break;
					}
				case CaretMovementType.PageUp:
				case CaretMovementType.PageDown:
					{
						// Page up/down: find the target line using its visual position
						double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle);
						if (direction == CaretMovementType.PageUp)
							yPos -= textArea.TextView.RenderSize.Height;
						else
							yPos += textArea.TextView.RenderSize.Height;
						DocumentLine newLine = textArea.TextView.GetDocumentLineByVisualTop(yPos);
						targetVisualLine = textArea.TextView.GetOrConstructVisualLine(newLine);
						targetLine = targetVisualLine.GetTextLineByVisualYPosition(yPos);
						break;
					}
				default:
					throw new NotSupportedException(direction.ToString());
			}
			if (targetLine != null) {
				double yPos = targetVisualLine.GetTextLineVisualYPosition(targetLine, VisualYPosition.LineMiddle);
				int newVisualColumn = targetVisualLine.GetVisualColumn(new Point(xPos, yPos), textArea.Selection.EnableVirtualSpace);
				SetCaretPosition(textArea, targetVisualLine, targetLine, newVisualColumn, false);
				textArea.Caret.DesiredXPos = xPos;
			}
		}
		#endregion
		
		#region SetCaretPosition
		static void SetCaretPosition(TextArea textArea, VisualLine targetVisualLine, TextLine targetLine,
		                             int newVisualColumn, bool allowWrapToNextLine)
		{
			int targetLineStartCol = targetVisualLine.GetTextLineVisualStartColumn(targetLine);
			if (!allowWrapToNextLine && newVisualColumn >= targetLineStartCol + targetLine.Length) {
				if (newVisualColumn <= targetVisualLine.VisualLength)
					newVisualColumn = targetLineStartCol + targetLine.Length - 1;
			}
			int newOffset = targetVisualLine.GetRelativeOffset(newVisualColumn) + targetVisualLine.FirstDocumentLine.Offset;
			SetCaretPosition(textArea, newVisualColumn, newOffset);
		}
		
		static void SetCaretPosition(TextArea textArea, int newVisualColumn, int newOffset)
		{
			textArea.Caret.Position = new TextViewPosition(textArea.Document.GetLocation(newOffset), newVisualColumn);
			textArea.Caret.DesiredXPos = double.NaN;
		}
		#endregion
	}
}