TextSelection.cs
上传用户:szltgg
上传日期:2019-05-16
资源大小:604k
文件大小:9k
源码类别:

Telnet服务器

开发平台:

C#

  1. /*
  2. * Copyright (c) 2005 Poderosa Project, All Rights Reserved.
  3. * $Id: TextSelection.cs,v 1.2 2005/04/20 08:45:48 okajima Exp $
  4. */
  5. using System;
  6. using System.Text;
  7. using System.Diagnostics;
  8. using Poderosa.Terminal;
  9. namespace Poderosa.Text
  10. {
  11. public enum RangeType {
  12. Char,
  13. Word,
  14. Line
  15. }
  16. public enum SelectionState {
  17. Empty,
  18. Pivot,
  19. Expansion,
  20. Fixed
  21. }
  22. /// <summary>
  23. /// 僥僉僗僩偺慖戰椞堟傪昞尰偡傞
  24. /// </summary>
  25. public class TextSelection {
  26. //抂揰
  27. internal struct TextPoint {
  28. public int   _line;
  29. public int   _position;
  30. public void Clear() {
  31. _line = -1;
  32. _position = 0;
  33. }
  34. }
  35. private SelectionState _state;
  36. private TerminalPane _owner;
  37. //嵟弶偺慖戰揰丅扨岅傗峴傪慖戰偟偨偲偒偺偨傔偵俀偮愝偗傞
  38. private TextPoint _forwardPivot;
  39. private TextPoint _backwardPivot;
  40. //慖戰偺嵟廔揰
  41. private TextPoint _forwardDestination;
  42. private TextPoint _backwardDestination;
  43. //pivot偺忬懺
  44. private RangeType _pivotType;
  45. //慖戰傪奐巒偟偨偲偒偺儅僂僗嵗昗
  46. private int _startX;
  47. private int _startY;
  48. //偪傚偭偲墭偄僼儔僌
  49. private bool _disabledTemporary;
  50. public TextSelection() {
  51. _owner = null;
  52. }
  53. public TerminalPane Owner {
  54. get {
  55. return _owner;
  56. }
  57. }
  58. public SelectionState State {
  59. get {
  60. return _state;
  61. }
  62. }
  63. public RangeType PivotType {
  64. get {
  65. return _pivotType;
  66. }
  67. }
  68. public int StartX {
  69. get {
  70. return _startX;
  71. }
  72. }
  73. public int StartY {
  74. get {
  75. return _startY;
  76. }
  77. }
  78. public void Clear() {
  79. if(_owner!=null) {
  80. _owner.ExitTextSelection();
  81. }
  82. _owner = null;
  83. _state = SelectionState.Empty;
  84. _pivotType = RangeType.Char;
  85. _forwardPivot.Clear();
  86. _backwardPivot.Clear();
  87. _forwardDestination.Clear();
  88. _backwardDestination.Clear();
  89. _disabledTemporary = false;
  90. }
  91. public void DisableTemporary() {
  92. _disabledTemporary = true;
  93. }
  94. //僪僉儏儊儞僩偑Discard偝傟偨偲偒偵屇偽傟傞丅first_line傛傝慜偵慖戰椞堟偑廳側偭偰偄偨傜僋儕傾偡傞
  95. public void ClearIfOverlapped(int first_line) {
  96. if(_forwardPivot._line!=-1 && _forwardPivot._line<first_line) {
  97. _forwardPivot._line = first_line;
  98. _forwardPivot._position = 0;
  99. _backwardPivot._line = first_line;
  100. _backwardPivot._position = 0;
  101. }
  102. if(_forwardDestination._line!=-1 && _forwardDestination._line<first_line) {
  103. _forwardDestination._line = first_line;
  104. _forwardDestination._position = 0;
  105. _backwardDestination._line = first_line;
  106. _backwardDestination._position = 0;
  107. }
  108. }
  109. public bool IsEmpty {
  110. get {
  111. return _owner==null || _forwardPivot._line==-1 || _backwardPivot._line==-1 |
  112. _forwardDestination._line==-1 || _backwardDestination._line==-1 || _disabledTemporary;
  113. }
  114. }
  115. internal bool StartSelection(TerminalPane owner, GLine line, int position, RangeType type, int x, int y) {
  116. Debug.Assert(owner!=null);
  117. Debug.Assert(position>=0);
  118. line.ExpandBuffer(position+1);
  119. _disabledTemporary = false;
  120. _owner = owner;
  121. _pivotType = type;
  122. _forwardPivot._line = line.ID;
  123. _backwardPivot._line = line.ID;
  124. _forwardDestination._line = line.ID;
  125. _forwardDestination._position = position;
  126. _backwardDestination._line = line.ID;
  127. _backwardDestination._position = position;
  128. switch(type) {
  129. case RangeType.Char:
  130. _forwardPivot._position = position;
  131. _backwardPivot._position = position;
  132. break;
  133. case RangeType.Word:
  134. _forwardPivot._position = line.FindPrevWordBreak(position)+1;
  135. _backwardPivot._position = line.FindNextWordBreak(position);
  136. break;
  137. case RangeType.Line:
  138. _forwardPivot._position = 0;
  139. _backwardPivot._position = line.CharLength;
  140. break;
  141. }
  142. _state = SelectionState.Pivot;
  143. _startX = x;
  144. _startY = y;
  145. return true;
  146. }
  147. internal bool ExpandTo(GLine line, int position, RangeType type) {
  148. line.ExpandBuffer(position+1);
  149. _disabledTemporary = false;
  150. _state = SelectionState.Expansion;
  151. _forwardDestination._line = line.ID;
  152. _backwardDestination._line = line.ID;
  153. //Debug.WriteLine(String.Format("ExpandTo Line{0} Position{1}", line.ID, position));
  154. switch(type) {
  155. case RangeType.Char:
  156. _forwardDestination._position = position;
  157. _backwardDestination._position = position;
  158. break;
  159. case RangeType.Word:
  160. _forwardDestination._position = line.FindPrevWordBreak(position)+1;
  161. _backwardDestination._position = line.FindNextWordBreak(position);
  162. break;
  163. case RangeType.Line:
  164. _forwardDestination._position = 0;
  165. _backwardDestination._position = line.CharLength;
  166. break;
  167. }
  168. return true;
  169. }
  170. internal void SelectAll(TerminalPane owner) {
  171. _disabledTemporary = false;
  172. Debug.Assert(owner!=null);
  173. _owner = owner;
  174. _forwardPivot._line = _owner.Document.FirstLine.ID;
  175. _forwardPivot._position = 0;
  176. _backwardPivot = _forwardPivot;
  177. _forwardDestination._line = _owner.Document.LastLine.ID;
  178. _forwardDestination._position = _owner.Document.LastLine.CharLength-1;
  179. _backwardDestination = _forwardDestination;
  180. _state = SelectionState.Fixed;
  181. _pivotType = RangeType.Char;
  182. }
  183. //儁僀儞奜傊儅僂僗傪僪儔僢僌偟偰偄偭偨応崌偵埵抲傪廋惓偡傞
  184. internal void ConvertSelectionPosition(ref int line_id, ref int col) {
  185. if(_pivotType==RangeType.Line) {
  186. if(line_id<=_forwardPivot._line)
  187. col = 0;
  188. else 
  189. col = _owner.Connection.TerminalWidth;
  190. }
  191. else {
  192. if(line_id<_forwardPivot._line) {
  193. if(col<0)
  194. col = 0;
  195. else if(col>=_owner.Connection.TerminalWidth) {
  196. line_id++;
  197. col = 0;
  198. }
  199. }
  200. else if(line_id==_forwardPivot._line) {
  201. if(col<0)
  202. col = 0;
  203. else if(col>=_owner.Connection.TerminalWidth)
  204. col = _owner.Connection.TerminalWidth;
  205. }
  206. else {
  207. if(col<0) {
  208. line_id--;
  209. col = _owner.Connection.TerminalWidth;
  210. }
  211. else if(col>=_owner.Connection.TerminalWidth)
  212. col = _owner.Connection.TerminalWidth;
  213. }
  214. }
  215. }
  216. internal void FixSelection() {
  217. _state = SelectionState.Fixed;
  218. }
  219. public string GetSelectedText() {
  220. return GetSelectedText(NLOption.Default);
  221. }
  222. public string GetSelectedTextAsLook() {
  223. return GetSelectedText(NLOption.AsLook);
  224. }
  225. private enum NLOption {
  226. Default,
  227. AsLook
  228. }
  229. private string GetSelectedText(NLOption opt) {
  230. if(_owner==null || _disabledTemporary) return null;
  231. StringBuilder bld = new StringBuilder();
  232. TextPoint a = HeadPoint;
  233. TextPoint b = TailPoint;
  234. GLine l = _owner.Document.FindLineOrEdge(a._line);
  235. int pos = a._position;
  236. do {
  237. bool eol_required = (opt==NLOption.AsLook || l.EOLType!=EOLType.Continue);
  238. if(l.ID==b._line) { //嵟廔峴
  239. //枛旜偵NULL暥帤偑擖傞働乕僗偑偁傞傛偆偩
  240. AppendTrim(bld, l.Text, pos, b._position-pos);
  241. if(_pivotType==RangeType.Line && eol_required)
  242. bld.Append("rn");
  243. break;
  244. }
  245. else { //嵟廔埲奜偺峴
  246. if(l.CharLength-pos>0) { //l.CharLength==pos偲側傞働乕僗偑偁偭偨丅恀偺棟桼偼擺摼偟偰偄側偄偑
  247. AppendTrim(bld, l.Text, pos, l.CharLength-pos);
  248. }
  249. if(eol_required && bld.Length>0) //bld.Length>0偼峴扨埵慖戰偱梋寁側夵峴偑擖傞偺傪旔偗傞偨傔偺張抲
  250. bld.Append("rn"); //LF偺傒傪僋儕僢僾儃乕僪偵帩偭偰偄偭偰傕懠偺傾僾儕偺崿棎偑偁傞偩偗側偺偱傗傔偰偍偔
  251. l = l.NextLine;
  252. if(l==null) break; //!!杮棃偙傟偼側偄偼偢偩偑僋儔僢僔儏儗億乕僩偺偨傔夞旔
  253. pos = 0;
  254. }
  255. } while(true);
  256. //Debug.WriteLine("Selected Text Len="+bld.Length);
  257. return bld.ToString();
  258. }
  259. private void AppendTrim(StringBuilder bld, char[] text, int pos, int length) {
  260. Debug.Assert(pos>=0);
  261. if(text[pos]==GLine.WIDECHAR_PAD) { //擔杮岅暥帤偺塃抂偐傜偺偲偒偼奼戝偡傞
  262. pos--;
  263. length++;
  264. }
  265. while(length-- > 0) {
  266. if(pos>=text.Length) break;
  267. char ch = text[pos++];
  268. if(ch!=GLine.WIDECHAR_PAD && ch!='') bld.Append(ch);
  269. }
  270. }
  271. internal TextPoint HeadPoint {
  272. get {
  273. return Min(ref _forwardPivot, ref _forwardDestination);
  274. }
  275. }
  276. internal TextPoint TailPoint {
  277. get {
  278. return Max(ref _backwardPivot, ref _backwardDestination);
  279. }
  280. }
  281. private static TextPoint Min(ref TextPoint p1, ref TextPoint p2) {
  282. int id1 = p1._line;
  283. int id2 = p2._line;
  284. if(id1==id2) {
  285. int pos1 = p1._position;
  286. int pos2 = p2._position;
  287. if(pos1==pos2)
  288. return p1;
  289. else
  290. return pos1<pos2? p1 : p2;
  291. }
  292. else
  293. return id1<id2? p1 : p2;
  294. }
  295. private static TextPoint Max(ref TextPoint p1, ref TextPoint p2) {
  296. int id1 = p1._line;
  297. int id2 = p2._line;
  298. if(id1==id2) {
  299. int pos1 = p1._position;
  300. int pos2 = p2._position;
  301. if(pos1==pos2)
  302. return p1;
  303. else
  304. return pos1>pos2? p1 : p2;
  305. }
  306. else
  307. return id1>id2? p1 : p2;
  308. }
  309. }
  310. }